package api

import (
	"api_gateway/basic/config"
	chat "api_gateway/basic/proto/chat"
	"api_gateway/untils"
	"context"
	"encoding/json"
	"fmt"
	"github.com/gorilla/websocket"
	"github.com/streadway/amqp"
	"log"
	"strconv"
	"sync"
	"time"
)

// 群成员数据结构
type GroupMember struct {
	UserID   int64  `json:"user_id"`
	JoinTime string `json:"join_time"`
	Role     int    `json:"role"` // 0:普通成员 1:管理员 2:群主
}

// 群信息结构
type GroupInfo struct {
	GroupID    int64          `json:"group_id"` // 改为int64保持一致性
	GroupName  string         `json:"group_name"`
	CreatorID  int64          `json:"creator_id"` // 改为int64
	CreateTime string         `json:"create_time"`
	Members    map[int64]bool `json:"members"` // 成员ID映射
}

// 全局变量
var (
	GroupInfos = make(map[int64]*GroupInfo) // 群信息缓存，key改为int64
	groupMutex = &sync.RWMutex{}
)

func PushGroupMessageToUser() {
	// 初始化rabbitmq连接
	rabbitmq := untils.NewRabbitMQSimple(config.GROUP_CHAT)

	// 从队列中获取消息
	groupMsg, err := rabbitmq.ConsumeSimple()
	if err != nil {
		log.Printf("从队列中获取群聊消息失败: %v", err)
		return
	}
	log.Printf(" [*] 群聊消息推送服务启动，等待消息...")

	// 处理消息
	for d := range groupMsg {
		// 保存到服务端并推送给在线用户
		go processGroupMessage(d)
	}
}

// 处理群聊消息
func processGroupMessage(d amqp.Delivery) {
	// 记录接收到的消息
	log.Printf("接收到群聊消息:%s", string(d.Body))

	// 解析消息为群聊消息结构体
	var groupMessage chat.SendGroupMessageReq
	if err := json.Unmarshal(d.Body, &groupMessage); err != nil {
		log.Printf("解析群聊消息失败: %v, 消息内容: %s", err, d.Body)
		d.Nack(false, false) // 解析失败，不重新入队
		return
	}

	// 设置调用服务端的超时上下文
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	// 调用服务端保存消息
	response, err := config.ChatClient.SendGroupMessage(ctx, &groupMessage)
	if err != nil {
		log.Printf("调用通讯服务失败: %v, 群ID: %s, 发送者: %d", err,
			groupMessage.GroupId, groupMessage.SenderId)
		d.Nack(false, true) // 服务调用失败，重新入队
		return
	}

	// 处理成功，确认消息
	d.Ack(false)

	log.Printf("群聊消息保存成功: 消息ID=%s, 群ID=%s, 发送者=%d",
		response.MessageId, groupMessage.GroupId, groupMessage.SenderId)

	// 推送给在线群成员
	go pushMessageToOnlineMembers(&groupMessage)
}

// 推送给在线群成员
func pushMessageToOnlineMembers(groupMessage *chat.SendGroupMessageReq) {
	groupId, err := strconv.ParseInt(groupMessage.GroupId, 10, 64)
	if err != nil {
		log.Printf("群ID转换失败: %s, 错误: %v", groupMessage.GroupId, err)
		return
	}

	// 构建推送消息
	pushMsg := map[string]interface{}{
		"type":         "groupMessage", // 修正消息类型
		"group_id":     groupId,
		"sender_id":    groupMessage.SenderId,
		"content":      groupMessage.Content,
		"message_type": groupMessage.MessageType,
		"timestamp":    time.Now().Unix(),
	}

	// 广播给群内在线成员（排除发送者自己）
	broadcastToGroupMembers(groupId, pushMsg, uint(groupMessage.SenderId))
}

// 验证用户是否在群内
func isUserInGroup(userId uint, groupId int64) bool {
	groupMutex.RLock()
	defer groupMutex.RUnlock()

	groupInfo, exists := GroupInfos[groupId]
	if !exists {
		// 如果缓存中没有，从数据库加载
		return loadGroupInfoFromDB(groupId) && GroupInfos[groupId].Members[int64(userId)]
	}

	return groupInfo.Members[int64(userId)]
}

// 从数据库加载群信息
func loadGroupInfoFromDB(groupId int64) bool {
	members, err := getGroupMembersFromDB(strconv.FormatInt(groupId, 10))
	if err != nil {
		log.Printf("从数据库加载群 %d 信息失败: %v", groupId, err)
		return false
	}

	groupMutex.Lock()
	defer groupMutex.Unlock()

	// 构建成员映射
	memberMap := make(map[int64]bool)
	for _, member := range members {
		memberMap[member.UserID] = true
	}

	GroupInfos[groupId] = &GroupInfo{
		GroupID: groupId,
		Members: memberMap,
	}

	log.Printf("群 %d 信息加载成功，成员数: %d", groupId, len(memberMap))
	return true
}

// 从数据库获取群成员列表
func getGroupMembersFromDB(groupId string) ([]GroupMember, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	resp, err := config.ChatClient.GetGroupMember(ctx, &chat.GetGroupMemberReq{
		GroupId: groupId,
	})
	if err != nil {
		return nil, fmt.Errorf("查询群成员失败：%v", err)
	}

	var members []GroupMember
	for _, member := range resp.Members {
		members = append(members, GroupMember{
			UserID:   member.UserId,
			JoinTime: member.JoinTime,
			Role:     int(member.Role),
		})
	}
	return members, nil
}

// 只广播给群内的在线成员
func broadcastToGroupMembers(groupId int64, message map[string]interface{}, senderId uint) {
	groupMutex.RLock()
	defer groupMutex.RUnlock()

	// 获取群在线成员
	onlineMembers, exists := GroupOnlineUser[groupId]
	if !exists {
		log.Printf("群 %d 没有在线成员", groupId)
		return
	}
	log.Printf("群 %d 有 %d 个在线成员，开始广播消息", groupId, len(onlineMembers))

	successCount := 0
	totalCount := 0

	for memberId, conn := range onlineMembers {
		totalCount++

		// 不发送给发送者自己
		if memberId == senderId {
			continue
		}

		if pushGroupMessageToUser(conn, message) {
			successCount++
			log.Printf("成功推送给用户 %d", memberId)
		} else {
			log.Printf("推送给用户 %d 失败", memberId)
		}
	}

	log.Printf("群 %d 消息广播完成: 成功推送 %d/%d 个在线群成员",
		groupId, successCount, totalCount)
}

// 推送群消息给用户
func pushGroupMessageToUser(conn *websocket.Conn, msgData map[string]interface{}) bool {
	response := WSResp{
		Code: 200,
		Msg:  "成功",
		Data: msgData, // 直接使用传入的消息数据
	}

	responseStr, err := json.Marshal(response)
	if err != nil {
		log.Printf("序列化消息失败: %v", err)
		return false
	}

	// 设置写超时
	conn.SetWriteDeadline(time.Now().Add(5 * time.Second))
	if err := conn.WriteMessage(websocket.TextMessage, responseStr); err != nil {
		log.Printf("推送消息失败: %v", err)
		return false
	}

	return true
}

// 用户加入所有所属群聊
func joinUserGroups(userId uint, conn *websocket.Conn) {
	// 获取用户所在的所有群聊
	groups, err := getUserGroupsFromDB(userId)
	if err != nil {
		log.Printf("获取用户 %d 的群列表失败: %v", userId, err)
		return
	}

	log.Printf("用户 %d 需要加入 %d 个群聊: %v", userId, len(groups), groups)

	successCount := 0
	for _, groupId := range groups {
		if joinGroup(userId, groupId, conn) {
			successCount++
			log.Printf("用户 %d 成功加入群 %d", userId, groupId)
		}
	}

	log.Printf("用户 %d 加入群聊完成: 成功加入 %d/%d 个群聊", userId, successCount, len(groups))
}

// 获取用户所在的所有群聊ID
func getUserGroupsFromDB(userId uint) ([]int64, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	// 调用服务端查询用户所在群聊
	resp, err := config.ChatClient.GetUserGroups(ctx, &chat.GetUserGroupsReq{
		UserId: int64(userId),
	})
	if err != nil {
		return nil, fmt.Errorf("查询用户 %d 所在群聊失败：%v", userId, err)
	}

	// 转换为int64类型的群聊ID列表
	var groupIds []int64
	for _, group := range resp.GroupIds {
		// 转换为int64类型
		groupID, _ := strconv.ParseInt(group.GroupId, 10, 64)
		groupIds = append(groupIds, groupID)
	}
	return groupIds, nil
}

// 用户加入群聊
func joinGroup(userId uint, groupId int64, conn *websocket.Conn) bool {
	groupOnlineUserLock.Lock()
	defer groupOnlineUserLock.Unlock()

	// 初始化群聊的在线用户映射
	if GroupOnlineUser[groupId] == nil {
		GroupOnlineUser[groupId] = make(map[uint]*websocket.Conn)
	}

	// 添加用户到群聊
	GroupOnlineUser[groupId][userId] = conn

	log.Printf("用户 %d 加入群 %d，当前在线成员: %d", userId, groupId, len(GroupOnlineUser[groupId]))

	return true
}
